from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont


class PythonHighlighter(QSyntaxHighlighter):
    """Python语法高亮器"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.highlighting_rules = []
        self.setup_rules()
    
    def setup_rules(self):
        """设置语法高亮规则"""
        
        # 关键字格式 - 橙色
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor('#CE713A'))  # 橙色
        keyword_format.setFontWeight(QFont.Bold)
        
        # Python关键字列表
        python_keywords = [
            'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del',
            'elif', 'else', 'except', 'False', 'finally', 'for', 'from', 'global',
            'if', 'import', 'in', 'is', 'lambda', 'None', 'nonlocal', 'not',
            'or', 'pass', 'raise', 'return', 'True', 'try', 'while', 'with', 'yield'
        ]
        
        # 为每个关键字创建规则
        for keyword in python_keywords:
            pattern = QRegExp(r'\b' + keyword + r'\b')
            self.highlighting_rules.append((pattern, keyword_format))
        
        # 函数名格式 - 蓝色
        function_format = QTextCharFormat()
        function_format.setForeground(QColor('#4E9AEF'))  # 蓝色
        function_pattern = QRegExp(r'\b[A-Za-z_][A-Za-z0-9_]*(?=\()')
        self.highlighting_rules.append((function_pattern, function_format))
        
        # 类名格式 - 青色
        class_format = QTextCharFormat()
        class_format.setForeground(QColor('#4EC9B0'))  # 青色
        class_format.setFontWeight(QFont.Bold)
        class_pattern = QRegExp(r'\bclass\s+([A-Za-z_][A-Za-z0-9_]*)')
        self.highlighting_rules.append((class_pattern, class_format))
        
        # 字符串格式 - 绿色
        string_format = QTextCharFormat()
        string_format.setForeground(QColor('#6A8759'))  # 绿色
        
        # 单引号字符串
        single_quote_pattern = QRegExp(r"'[^'\\]*(\\.[^'\\]*)*'")
        self.highlighting_rules.append((single_quote_pattern, string_format))
        
        # 双引号字符串
        double_quote_pattern = QRegExp(r'"[^"\\]*(\\.[^"\\]*)*"')
        self.highlighting_rules.append((double_quote_pattern, string_format))
        
        # 三引号字符串（多行字符串）
        triple_single_pattern = QRegExp(r"'''[^'\\]*(\\.[^'\\]*)*'''")
        self.highlighting_rules.append((triple_single_pattern, string_format))
        
        triple_double_pattern = QRegExp(r'"""[^"\\]*(\\.[^"\\]*)*"""')
        self.highlighting_rules.append((triple_double_pattern, string_format))
        
        # 注释格式 - 灰色
        comment_format = QTextCharFormat()
        comment_format.setForeground(QColor('#808080'))  # 灰色
        comment_pattern = QRegExp(r'#[^\n]*')
        self.highlighting_rules.append((comment_pattern, comment_format))
        
        # 数字格式 - 紫色
        number_format = QTextCharFormat()
        number_format.setForeground(QColor('#B5CEA8'))  # 浅紫色
        number_pattern = QRegExp(r'\b\d+\.?\d*\b')
        self.highlighting_rules.append((number_pattern, number_format))
        
        # 装饰器格式 - 粉色
        decorator_format = QTextCharFormat()
        decorator_format.setForeground(QColor('#CE9178'))  # 粉色
        decorator_pattern = QRegExp(r'@[A-Za-z_][A-Za-z0-9_]*')
        self.highlighting_rules.append((decorator_pattern, decorator_format))
        
        # 特殊方法格式 - 深蓝色
        special_method_format = QTextCharFormat()
        special_method_format.setForeground(QColor('#569CD6'))  # 深蓝色
        special_method_pattern = QRegExp(r'\b__[a-z]+__\b')
        self.highlighting_rules.append((special_method_pattern, special_method_format))
        
        # 内置函数格式 - 浅黄色
        builtin_format = QTextCharFormat()
        builtin_format.setForeground(QColor('#DCDCAA'))  # 浅黄色
        
        # Python内置函数列表
        builtin_functions = [
            'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray',
            'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex',
            'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec',
            'filter', 'float', 'format', 'frozenset', 'getattr', 'globals',
            'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
            'issubclass', 'iter', 'len', 'list', 'locals', 'map', 'max', 'memoryview',
            'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
            'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
            'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
            'vars', 'zip', '__import__'
        ]
        
        for builtin in builtin_functions:
            pattern = QRegExp(r'\b' + builtin + r'\b')
            self.highlighting_rules.append((pattern, builtin_format))
    
    def highlightBlock(self, text):
        """高亮文本块"""
        # 先处理多行字符串（需要特殊处理）
        self.highlight_multiline_strings(text)
        
        # 然后处理其他规则
        for pattern, format_ in self.highlighting_rules:
            expression = QRegExp(pattern)
            index = expression.indexIn(text)
            while index >= 0:
                length = expression.matchedLength()
                # 检查是否已经在字符串中（多行字符串状态）
                if self.currentBlockState() != 1:
                    self.setFormat(index, length, format_)
                index = expression.indexIn(text, index + length)
    
    def highlight_multiline_strings(self, text):
        """处理多行字符串高亮"""
        # 获取前一个块的状态
        previous_state = self.previousBlockState()
        
        # 字符串格式
        string_format = QTextCharFormat()
        string_format.setForeground(QColor('#6A8759'))  # 绿色
        
        start_index = 0
        
        # 如果前一个块在多行字符串中，继续高亮
        if previous_state == 1:
            start_index = 0
            self.setFormat(0, len(text), string_format)
            
            # 查找字符串结束位置
            end_pattern = QRegExp(r'("""|\'\'\')')
            end_index = end_pattern.indexIn(text)
            if end_index >= 0:
                # 字符串结束，重置状态
                self.setCurrentBlockState(0)
            else:
                # 字符串继续到下一行
                self.setCurrentBlockState(1)
            return
        
        # 查找多行字符串开始
        start_pattern = QRegExp(r'("""|\'\'\')')
        start_index = start_pattern.indexIn(text)
        
        while start_index >= 0:
            # 查找字符串结束
            end_pattern = QRegExp(r'("""|\'\'\')')
            end_index = end_pattern.indexIn(text, start_index + 3)
            
            if end_index == -1:
                # 字符串跨越多行
                self.setFormat(start_index, len(text) - start_index, string_format)
                self.setCurrentBlockState(1)
                break
            else:
                # 单行内的多行字符串
                self.setFormat(start_index, end_index - start_index + 3, string_format)
                start_index = end_pattern.indexIn(text, end_index + 3)